home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / ra68k.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  84KB  |  2,207 lines

  1. {
  2.     $Id: ra68k.pas,v 1.1.1.1.2.1 1998/07/01 13:57:09 carl Exp $
  3.     Copyright (c) 1997-98 by Carl Eric Codere
  4.  
  5.     This unit does the parsing process for the motorola inline assembler
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23. Unit Ra68k;
  24. {**********************************************************************}
  25. { WARNING                                                              }
  26. {**********************************************************************}
  27. {  Any modification in the order or removal of terms in the tables     }
  28. {  in m68k.pas and asmo68k.pas  will BREAK the code in this unit,      }
  29. {  unless the appropriate changes are made to this unit. Addition      }
  30. {  of terms though, will not change the code herein.                   }
  31. {**********************************************************************}
  32.  
  33. {---------------------------------------------------------------------------}
  34. { LEFT TO DO                                                                }
  35. {---------------------------------------------------------------------------}
  36. {  o Add support for sized indexing such as in d0.l                         }
  37. {      presently only (an,dn) is supported for indexing --                  }
  38. {        size defaults to LONG.                                             }
  39. {  o Add support for MC68020 opcodes.                                       }
  40. {  o Add support for MC68020 adressing modes.                               }
  41. {  o Add operand checking with m68k opcode table in ConcatOpCode            }
  42. {  o Add Floating point support                                             }
  43. {---------------------------------------------------------------------------}
  44.  
  45. Interface
  46.  
  47. Uses
  48.   m68k,tree;
  49.  
  50.    function assemble: ptree;
  51.  
  52. const
  53.  { this variable is TRUE if the lookup tables have already been setup  }
  54.  { for fast access. On the first call to assemble the tables are setup }
  55.  { and stay set up.                                                    }
  56.  _asmsorted: boolean = FALSE;
  57.  firstreg       = R_D0;
  58.  lastreg        = R_FPSR;
  59.  
  60. type
  61.  tiasmops = array[firstop..lastop] of string[7];
  62.  piasmops = ^tiasmops;
  63.  
  64.  tasmkeyword = string[6];
  65.  
  66. var
  67.  { sorted tables of opcodes }
  68.  iasmops: piasmops;
  69.  { uppercased tables of registers }
  70.  iasmregs: array[firstreg..lastreg] of string[6];
  71.  
  72.  
  73. Implementation
  74.  
  75. uses
  76.   globals,AsmUtils,strings,hcodegen,scanner,aasm,
  77.   cobjects,verbose,symtable;
  78.  
  79.  
  80. type
  81.  tmotorolatoken = (
  82.    AS_NONE,AS_LABEL,AS_LLABEL,AS_STRING,AS_HEXNUM,AS_OCTALNUM,
  83.    AS_BINNUM,AS_COMMA,AS_LBRACKET,AS_RBRACKET,AS_LPAREN,
  84.    AS_RPAREN,AS_COLON,AS_DOT,AS_PLUS,AS_MINUS,AS_STAR,AS_INTNUM,
  85.    AS_SEPARATOR,AS_ID,AS_REGISTER,AS_OPCODE,AS_SLASH,AS_APPT,AS_REALNUM,
  86.    AS_ALIGN,
  87.      {------------------ Assembler directives --------------------}
  88.    AS_DB,AS_DW,AS_DD,AS_XDEF,AS_END,
  89.      {------------------ Assembler Operators  --------------------}
  90.    AS_MOD,AS_SHL,AS_SHR,AS_NOT,AS_AND,AS_OR,AS_XOR);
  91.  
  92. const
  93.    firstdirective = AS_DB;
  94.    lastdirective  = AS_END;
  95.    firstoperator  = AS_MOD;
  96.    lastoperator   = AS_XOR;
  97.  
  98.    _count_asmdirectives = longint(lastdirective)-longint(firstdirective);
  99.    _count_asmoperators  = longint(lastoperator)-longint(firstoperator);
  100.  
  101.    _asmdirectives : array[0.._count_asmdirectives] of tasmkeyword =
  102.     ('DC.B','DC.W','DC.L','XDEF','END');
  103.  
  104.     { problems with shl,shr,not,and,or and xor, they are }
  105.     { context sensitive.                                 }
  106.     _asmoperators : array[0.._count_asmoperators] of tasmkeyword = (
  107.     'MOD','SHL','SHR','NOT','AND','OR','XOR');
  108.  
  109.  
  110. const
  111.   newline = #10;
  112.   firsttoken : boolean = TRUE;
  113.   operandnum : byte = 0;
  114. var
  115.  p : paasmoutput;
  116.  actasmtoken: tmotorolatoken;
  117.  actasmpattern: string;
  118.  c: char;
  119.  Instr: TInstruction;
  120.  labellist: TAsmLabelList;
  121.  old_exit : pointer;
  122.  
  123.    Procedure SetupTables;
  124.    { creates uppercased symbol tables for speed access }
  125.    var
  126.      i: tasmop;
  127.      j: tregister;
  128.    Begin
  129.      Message(assem_d_creating_lookup_tables);
  130.      { opcodes }
  131.      new(iasmops);
  132.      for i:=firstop to lastop do
  133.       iasmops^[i] := upper(mot_op2str[i]);
  134.      { opcodes }
  135.      for j:=firstreg to lastreg do
  136.       iasmregs[j] := upper(mot_reg2str[j]);
  137.    end;
  138.  
  139.  
  140.     procedure ra68k_exit;far;
  141.       begin
  142.          if assigned(iasmops) then
  143.            dispose(iasmops);
  144.          exitproc:=old_exit;
  145.       end;
  146.  
  147.   {---------------------------------------------------------------------}
  148.   {                     Routines for the tokenizing                     }
  149.   {---------------------------------------------------------------------}
  150.  
  151.  
  152.    function is_asmopcode(s: string):Boolean;
  153.   {*********************************************************************}
  154.   { FUNCTION is_asmopcode(s: string):Boolean                            }
  155.   {  Description: Determines if the s string is a valid opcode          }
  156.   {  if so returns TRUE otherwise returns FALSE.                        }
  157.   {  Remark: Suffixes are also checked, as long as they are valid.      }
  158.   {*********************************************************************}
  159.    var
  160.     i: tasmop;
  161.     j: byte;
  162.    Begin
  163.      is_asmopcode := FALSE;
  164.      { first of all we remove the suffix }
  165.      j:=pos('.',s);
  166.      if j<>0 then
  167.       delete(s,j,2);
  168.      for i:=firstop to lastop do
  169.      begin
  170.        if  s = iasmops^[i] then
  171.        begin
  172.           is_asmopcode:=TRUE;
  173.           exit;
  174.        end;
  175.      end;
  176.    end;
  177.  
  178.  
  179.  
  180.    Procedure is_asmdirective(const s: string; var token: tmotorolatoken);
  181.   {*********************************************************************}
  182.   { FUNCTION is_asmdirective(s: string; var token: tinteltoken):Boolean }
  183.   {  Description: Determines if the s string is a valid directive       }
  184.   { (an operator can occur in operand fields, while a directive cannot) }
  185.   {  if so returns the directive token, otherwise does not change token.}
  186.   {*********************************************************************}
  187.    var
  188.     i:byte;
  189.    Begin
  190.      for i:=0 to _count_asmdirectives do
  191.      begin
  192.         if s=_asmdirectives[i] then
  193.         begin
  194.            token := tmotorolatoken(longint(firstdirective)+i);
  195.            exit;
  196.         end;
  197.      end;
  198.    end;
  199.  
  200.  
  201.    Procedure is_register(const s: string; var token: tmotorolatoken);
  202.   {*********************************************************************}
  203.   { PROCEDURE is_register(s: string; var token: tinteltoken);           }
  204.   {  Description: Determines if the s string is a valid register, if    }
  205.   {  so return token equal to A_REGISTER, otherwise does not change token}
  206.   {*********************************************************************}
  207.    Var
  208.     i: tregister;
  209.    Begin
  210.      for i:=firstreg to lastreg do
  211.      begin
  212.       if s=iasmregs[i] then
  213.       begin
  214.         token := AS_REGISTER;
  215.         exit;
  216.       end;
  217.      end;
  218.      { take care of other name for sp }
  219.      if s = 'A7' then
  220.      begin
  221.       token:=AS_REGISTER;
  222.       exit;
  223.      end;
  224.    end;
  225.  
  226.  
  227.  
  228.   Function GetToken: tmotorolatoken;
  229.   {*********************************************************************}
  230.   { FUNCTION GetToken: tinteltoken;                                     }
  231.   {  Description: This routine returns intel assembler tokens and       }
  232.   {  does some minor syntax error checking.                             }
  233.   {*********************************************************************}
  234.   var
  235.    j: integer;
  236.    token: tmotorolatoken;
  237.    forcelabel: boolean;
  238.    errorflag : boolean;
  239.   begin
  240.     errorflag := FALSE;
  241.     forcelabel := FALSE;
  242.     actasmpattern :='';
  243.     {* INIT TOKEN TO NOTHING *}
  244.     token := AS_NONE;
  245.     { while space and tab , continue scan... }
  246.     while (c = ' ') or (c = #9) do
  247.     begin
  248.       c := asmgetchar;
  249.     end;
  250.     { Possiblities for first token in a statement:                }
  251.     {   Local Label, Label, Directive, Prefix or Opcode....       }
  252.     if firsttoken and not (c in [newline,#13,'{',';']) then
  253.     begin
  254.  
  255.       firsttoken := FALSE;
  256.       if c = '@' then
  257.       begin
  258.         token := AS_LLABEL;   { this is a local label }
  259.         { Let us point to the next character }
  260.         c := asmgetchar;
  261.       end;
  262.  
  263.  
  264.  
  265.       while c in ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
  266.       begin
  267.          { if there is an at_sign, then this must absolutely be a label }
  268.          if c = '@' then forcelabel:=TRUE;
  269.          actasmpattern := actasmpattern + c;
  270.          c := asmgetchar;
  271.       end;
  272.  
  273.       uppervar(actasmpattern);
  274.  
  275.       if c = ':' then
  276.       begin
  277.            case token of
  278.              AS_NONE: token := AS_LABEL;
  279.              AS_LLABEL: ; { do nothing }
  280.            end; { end case }
  281.            { let us point to the next character }
  282.            c := asmgetchar;
  283.            gettoken := token;
  284.            exit;
  285.       end;
  286.  
  287.       { Are we trying to create an identifier with }
  288.       { an at-sign...?                             }
  289.       if forcelabel then
  290.        Message(assem_e_none_label_contain_at);
  291.  
  292.       If is_asmopcode(actasmpattern) then
  293.       Begin
  294.        gettoken := AS_OPCODE;
  295.        exit;
  296.       end;
  297.       is_asmdirective(actasmpattern, token);
  298.       if (token <> AS_NONE) then
  299.       Begin
  300.         gettoken := token;
  301.         exit
  302.       end
  303.       else
  304.       begin
  305.          gettoken := AS_NONE;
  306.          Message1(assem_e_invalid_operand,actasmpattern);
  307.       end;
  308.     end
  309.     else { else firsttoken }
  310.     { Here we must handle all possible cases                              }
  311.     begin
  312.       case c of
  313.  
  314.          '@':   { possiblities : - local label reference , such as in jmp @local1 }
  315.                 {                - @Result, @Code or @Data special variables.     }
  316.                             begin
  317.                              actasmpattern := c;
  318.                              c:= asmgetchar;
  319.                              while c in  ['A'..'Z','a'..'z','0'..'9','_','@','.'] do
  320.                              begin
  321.                                actasmpattern := actasmpattern + c;
  322.                                c := asmgetchar;
  323.                              end;
  324.                              uppervar(actasmpattern);
  325.                              gettoken := AS_ID;
  326.                              exit;
  327.                             end;
  328.       { identifier, register, opcode, prefix or directive }
  329.          'A'..'Z','a'..'z','_': begin
  330.                              actasmpattern := c;
  331.                              c:= asmgetchar;
  332.                              while c in  ['A'..'Z','a'..'z','0'..'9','_','.'] do
  333.                              begin
  334.                                actasmpattern := actasmpattern + c;
  335.                                c := asmgetchar;
  336.                              end;
  337.                              uppervar(actasmpattern);
  338.  
  339.                              If is_asmopcode(actasmpattern) then
  340.                              Begin
  341.                                     gettoken := AS_OPCODE;
  342.                                     exit;
  343.                              end;
  344.                              is_register(actasmpattern, token);
  345.                              {is_asmoperator(actasmpattern,token);}
  346.                              is_asmdirective(actasmpattern,token);
  347.                              { if found }
  348.                              if (token <> AS_NONE) then
  349.                              begin
  350.                                gettoken := token;
  351.                                exit;
  352.                              end
  353.                              { this is surely an identifier }
  354.                              else
  355.                                token := AS_ID;
  356.                              gettoken := token;
  357.                              exit;
  358.                           end;
  359.            { override operator... not supported }
  360.            '&':       begin
  361.                          c:=asmgetchar;
  362.                          gettoken := AS_AND;
  363.                       end;
  364.            { string or character }
  365.            '''' :
  366.                       begin
  367.                          actasmpattern:='';
  368.                          while true do
  369.                          begin
  370.                            if c = '''' then
  371.                            begin
  372.                               c:=asmgetchar;
  373.                               if c=newline then
  374.                               begin
  375.                                  Message(scan_f_string_exceeds_line);
  376.                                  break;
  377.                               end;
  378.                               repeat
  379.                                   if c=''''then
  380.                                    begin
  381.                                        c:=asmgetchar;
  382.                                        if c='''' then
  383.                                         begin
  384.                                                actasmpattern:=actasmpattern+'''';
  385.                                                c:=asmgetchar;
  386.                                                if c=newline then
  387.                                                begin
  388.                                                     Message(scan_f_string_exceeds_line);
  389.                                                     break;
  390.                                                end;
  391.                                         end
  392.                                         else break;
  393.                                    end
  394.                                    else
  395.                                    begin
  396.                                           actasmpattern:=actasmpattern+c;
  397.                                           c:=asmgetchar;
  398.                                           if c=newline then
  399.                                             begin
  400.                                                Message(scan_f_string_exceeds_line);
  401.                                                break
  402.                                             end;
  403.                                    end;
  404.                               until false; { end repeat }
  405.                            end
  406.                            else break; { end if }
  407.                          end; { end while }
  408.                    token:=AS_STRING;
  409.                    gettoken := token;
  410.                    exit;
  411.                  end;
  412.            '$' :  begin
  413.                     c:=asmgetchar;
  414.                     while c in ['0'..'9','A'..'F','a'..'f'] do
  415.                     begin
  416.                       actasmpattern := actasmpattern + c;
  417.                       c := asmgetchar;
  418.                     end;
  419.                    gettoken := AS_HEXNUM;
  420.                    exit;
  421.                   end;
  422.            ',' : begin
  423.                    gettoken := AS_COMMA;
  424.                    c:=asmgetchar;
  425.                    exit;
  426.                  end;
  427.            '(' : begin
  428.                    gettoken := AS_LPAREN;
  429.                    c:=asmgetchar;
  430.                    exit;
  431.                  end;
  432.            ')' : begin
  433.                    gettoken := AS_RPAREN;
  434.                    c:=asmgetchar;
  435.                    exit;
  436.                  end;
  437.            ':' : begin
  438.                    gettoken := AS_COLON;
  439.                    c:=asmgetchar;
  440.                    exit;
  441.                  end;
  442. {           '.' : begin
  443.                    gettoken := AS_DOT;
  444.                    c:=asmgetchar;
  445.                    exit;
  446.                  end; }
  447.            '+' : begin
  448.                    gettoken := AS_PLUS;
  449.                    c:=asmgetchar;
  450.                    exit;
  451.                  end;
  452.            '-' : begin
  453.                    gettoken := AS_MINUS;
  454.                    c:=asmgetchar;
  455.                    exit;
  456.                  end;
  457.            '*' : begin
  458.                    gettoken := AS_STAR;
  459.                    c:=asmgetchar;
  460.                    exit;
  461.                  end;
  462.            '/' : begin
  463.                    gettoken := AS_SLASH;
  464.                    c:=asmgetchar;
  465.                    exit;
  466.                  end;
  467.            '<' : begin
  468.                    c := asmgetchar;
  469.                    { invalid characters }
  470.                    if c <> '<' then
  471.                     Message(assem_e_invalid_char_smaller);
  472.                    { still assume << }
  473.                    gettoken := AS_SHL;
  474.                    c := asmgetchar;
  475.                    exit;
  476.                  end;
  477.            '>' : begin
  478.                    c := asmgetchar;
  479.                    { invalid characters }
  480.                    if c <> '>' then
  481.                     Message(assem_e_invalid_char_greater);
  482.                    { still assume << }
  483.                    gettoken := AS_SHR;
  484.                    c := asmgetchar;
  485.                    exit;
  486.                  end;
  487.            '|' : begin
  488.                    gettoken := AS_OR;
  489.                    c := asmgetchar;
  490.                    exit;
  491.                  end;
  492.            '^' : begin
  493.                   gettoken := AS_XOR;
  494.                   c := asmgetchar;
  495.                   exit;
  496.                  end;
  497.            '#' : begin
  498.                   gettoken:=AS_APPT;
  499.                   c:=asmgetchar;
  500.                   exit;
  501.                  end;
  502.            '%' : begin
  503.                    c:=asmgetchar;
  504.                    while c in ['0','1'] do
  505.                    Begin
  506.                      actasmpattern := actasmpattern + c;
  507.                      c := asmgetchar;
  508.                    end;
  509.                    gettoken := AS_BINNUM;
  510.                    exit;
  511.                  end;
  512.            { integer number }
  513.            '0'..'9': begin
  514.                         actasmpattern := c;
  515.                         c := asmgetchar;
  516.                         while c in ['0'..'9'] do
  517.                           Begin
  518.                              actasmpattern := actasmpattern + c;
  519.                              c:= asmgetchar;
  520.                           end;
  521.                         gettoken := AS_INTNUM;
  522.                         exit;
  523.                      end;
  524.          ';' : begin
  525.                   repeat
  526.                      c:=asmgetchar;
  527.                   until c=newline;
  528.                   firsttoken := TRUE;
  529.                   gettoken:=AS_SEPARATOR;
  530.                end;
  531.  
  532.          '{',#13,newline : begin
  533.                             c:=asmgetchar;
  534.                             firsttoken := TRUE;
  535.                             gettoken:=AS_SEPARATOR;
  536.                            end;
  537.             else
  538.              Begin
  539.                Message(scan_f_illegal_char);
  540.              end;
  541.  
  542.       end; { end case }
  543.     end; { end else if }
  544.   end;
  545.  
  546.  
  547.   {---------------------------------------------------------------------}
  548.   {                     Routines for the parsing                        }
  549.   {---------------------------------------------------------------------}
  550.  
  551.      procedure consume(t : tmotorolatoken);
  552.  
  553.      begin
  554.        if t<>actasmtoken then
  555.         Message(assem_e_syntax_error);
  556.        actasmtoken:=gettoken;
  557.        { if the token must be ignored, then }
  558.        { get another token to parse.        }
  559.        if actasmtoken = AS_NONE then
  560.           actasmtoken := gettoken;
  561.       end;
  562.  
  563.  
  564.  
  565.  
  566.  
  567.    function findregister(const s : string): tregister;
  568.   {*********************************************************************}
  569.   { FUNCTION findregister(s: string):tasmop;                            }
  570.   {  Description: Determines if the s string is a valid register,       }
  571.   {  if so returns correct tregister token, or R_NO if not found.       }
  572.   {*********************************************************************}
  573.    var
  574.     i: tregister;
  575.    begin
  576.      findregister := R_NO;
  577.      for i:=firstreg to lastreg do
  578.        if s = iasmregs[i] then
  579.        Begin
  580.          findregister := i;
  581.          exit;
  582.        end;
  583.     if s = 'A7' then
  584.     Begin
  585.       findregister := R_SP;
  586.       exit;
  587.     end;
  588.    end;
  589.  
  590.  
  591.    function findopcode(s: string): tasmop;
  592.   {*********************************************************************}
  593.   { FUNCTION findopcode(s: string): tasmop;                             }
  594.   {  Description: Determines if the s string is a valid opcode          }
  595.   {  if so returns correct tasmop token.                                }
  596.   {*********************************************************************}
  597.    var
  598.     i: tasmop;
  599.     j: byte;
  600.     op_size: string;
  601.    Begin
  602.      findopcode := A_NONE;
  603.      j:=pos('.',s);
  604.      if j<>0 then
  605.      begin
  606.        op_size:=copy(s,j+1,1);
  607.        case op_size[1] of
  608.        { For the motorola only stropsize size is used to }
  609.        { determine the size of the operands.             }
  610.        'B': instr.stropsize := S_B;
  611.        'W': instr.stropsize := S_W;
  612.        'L': instr.stropsize := S_L;
  613.        'S': instr.stropsize := S_S;
  614.        'D': instr.stropsize := S_Q;
  615.        'X': instr.stropsize := S_X;
  616.        else
  617.         Message1(assem_e_invalid_opcode,s);
  618.        end;
  619.        { delete everything starting from dot }
  620.        delete(s,j,length(s));
  621.      end;
  622.      for i:=firstop to lastop do
  623.        if  s = iasmops^[i] then
  624.        begin
  625.           findopcode:=i;
  626.           exit;
  627.        end;
  628.    end;
  629.  
  630.   Procedure InitAsmRef(var instr: TInstruction);
  631.   {*********************************************************************}
  632.   {  Description: This routine first check if the instruction is of     }
  633.   {  type OPR_NONE, or OPR_REFERENCE , if not it gives out an error.    }
  634.   {  If the operandtype = OPR_NONE or <> OPR_REFERENCE then it sets up  }
  635.   {  the operand type to OPR_REFERENCE, as well as setting up the ref   }
  636.   {  to point to the default segment.                                   }
  637.   {*********************************************************************}
  638.    Begin
  639.      With instr do
  640.      Begin
  641.         case operands[operandnum].operandtype of
  642.           OPR_REFERENCE: exit;
  643.           OPR_NONE: ;
  644.         else
  645.           Message(assem_e_invalid_operand_type);
  646.         end;
  647.         operands[operandnum].ref.direction := dir_none;
  648.         operands[operandnum].operandtype := OPR_REFERENCE;
  649.         operands[operandnum].ref.segment := R_DEFAULT_SEG;
  650.      end;
  651.    end;
  652.  
  653.  
  654.  
  655.  
  656.   Function CalculateExpression(expression: string): longint;
  657.   var
  658.     expr: TExprParse;
  659.   Begin
  660.    expr.Init;
  661.    CalculateExpression := expr.Evaluate(expression);
  662.    expr.Done;
  663.   end;
  664.  
  665.  
  666.   Procedure ConcatOpCode(var instr: TInstruction);
  667.   var
  668.     fits : boolean;
  669.     i: longint;
  670.     opsize: topsize;
  671.     optyp1, optyp2, optyp3: longint;
  672.     instruc: tasmop;
  673.     op: tasmop;
  674.   Begin
  675.      fits := FALSE;
  676.     { setup specific instructions for first pass }
  677.     instruc := instr.getinstruction;
  678.  
  679.     { Setup special operands }
  680.     { Convert to general form as to conform to the m68k opcode table }
  681.     if (instruc = A_ADDA) or (instruc = A_ADDI)
  682.        then instruc := A_ADD
  683.     else
  684.     { CMPM excluded because of GAS v1.34 BUG }
  685.     if (instruc = A_CMPA) or
  686.        (instruc = A_CMPI) then
  687.        instruc := A_CMP
  688.     else
  689.     if instruc = A_EORI then
  690.       instruc := A_EOR
  691.     else
  692.     if instruc = A_MOVEA then
  693.      instruc := A_MOVE
  694.     else
  695.     if instruc = A_ORI then
  696.       instruc := A_OR
  697.     else
  698.     if (instruc = A_SUBA) or (instruc = A_SUBI) then
  699.       instruc :=  A_SUB;
  700.  
  701.     { Setup operand types }
  702.  
  703. (*
  704.     in instruc <> A_MOVEM then
  705.     Begin
  706.  
  707.       while not(fits) do
  708.         begin
  709.          { set the instruction cache, if the instruction }
  710.          { occurs the first time                         }
  711.          if (it[i].i=instruc) and (ins_cache[instruc]=-1) then
  712.              ins_cache[instruc]:=i;
  713.  
  714.          if (it[i].i=instruc) and (instr.numops=it[i].ops) then
  715.          begin
  716.             { first fit }
  717.            case instr.numops of
  718.              0 : begin
  719.                    fits:=true;
  720.                    break;
  721.                 end;
  722.             1 :
  723.                 Begin
  724.                   if (optyp1 and it[i].o1)<>0 then
  725.                   Begin
  726.                     fits:=true;
  727.                      break;
  728.                   end;
  729.                 end;
  730.             2 : if ((optyp1 and it[i].o1)<>0) and
  731.                  ((optyp2 and it[i].o2)<>0) then
  732.                  Begin
  733.                        fits:=true;
  734.                        break;
  735.                  end
  736.             3 : if ((optyp1 and it[i].o1)<>0) and
  737.                  ((optyp2 and it[i].o2)<>0) and
  738.                  ((optyp3 and it[i].o3)<>0) then
  739.                  Begin
  740.                    fits:=true;
  741.                    break;
  742.                  end;
  743.            end; { end case }
  744.         end; { endif }
  745.         if it[i].i=A_NONE then
  746.         begin
  747.           { NO MATCH! }
  748.           Message(assem_e_invalid_combination_opcode_and_operand);
  749.           exit;
  750.         end;
  751.         inc(i);
  752.        end; { end while }
  753.              *)
  754.   fits:=TRUE;
  755.  
  756.   { We add the opcode to the opcode linked list }
  757.   if fits then
  758.   Begin
  759.     case instr.numops of
  760.      0:
  761.         if instr.stropsize <> S_NO then
  762.           p^.concat(new(pai68k,op_none(instruc,instr.stropsize)))
  763.         else
  764.           p^.concat(new(pai68k,op_none(instruc,S_NO)));
  765.      1: Begin
  766.           case instr.operands[1].operandtype of
  767.            OPR_CONSTANT: Begin
  768.                              p^.concat(new(pai68k,op_const(instruc,
  769.                                instr.stropsize, instr.operands[1].val)));
  770.                          end;
  771.            OPR_REGISTER:  p^.concat(new(pai68k,op_reg(instruc,
  772.                             instr.stropsize,instr.operands[1].reg)));
  773.            OPR_REFERENCE:
  774.                           if instr.stropsize <> S_NO then
  775.                           Begin
  776.                            p^.concat(new(pai68k,op_ref(instruc,
  777.                             instr.stropsize,newreference(instr.operands[1].ref))));
  778.                           end
  779.                           else
  780.                           Begin
  781.                               { special jmp and call case with }
  782.                               { symbolic references.           }
  783.                               if instruc in [A_BSR,A_JMP,A_JSR,A_BRA,A_PEA] then
  784.                               Begin
  785.                                 p^.concat(new(pai68k,op_ref(instruc,
  786.                                   S_NO,newreference(instr.operands[1].ref))));
  787.                               end
  788.                               else
  789.                                 Message(assem_e_invalid_opcode_and_operand);
  790.                           end;
  791.            OPR_NONE: Begin
  792.                        Message(assem_f_internal_error_in_concatopcode);
  793.                      end;
  794.           else
  795.            Begin
  796.              Message(assem_f_internal_error_in_concatopcode);
  797.            end;
  798.           end;
  799.         end;
  800.      2:
  801.         Begin
  802.                 With instr do
  803.                 Begin
  804.                 { source }
  805.                   case operands[1].operandtype of
  806.                   { reg,reg     }
  807.                   { reg,ref     }
  808.                    OPR_REGISTER:
  809.                      Begin
  810.                        case operands[2].operandtype of
  811.                          OPR_REGISTER:
  812.                             Begin
  813.                                p^.concat(new(pai68k,op_reg_reg(instruc,
  814.                                stropsize,operands[1].reg,operands[2].reg)));
  815.                             end;
  816.                          OPR_REFERENCE:
  817.                                   p^.concat(new(pai68k,op_reg_ref(instruc,
  818.                                   stropsize,operands[1].reg,newreference(operands[2].ref))));
  819.                        else { else case }
  820.                          Begin
  821.                            Message(assem_f_internal_error_in_concatopcode);
  822.                          end;
  823.                        end; { end inner case }
  824.                      end;
  825.                   { reglist, ref }
  826.                    OPR_REGLIST:
  827.                           Begin
  828.                             case operands[2].operandtype of
  829.                               OPR_REFERENCE :
  830.                                   p^.concat(new(pai68k,op_reglist_ref(instruc,
  831.                                   stropsize,operands[1].list,newreference(operands[2].ref))));
  832.                             else
  833.                              Begin
  834.                                Message(assem_f_internal_error_in_concatopcode);
  835.                              end;
  836.                             end; { end case }
  837.                           end;
  838.  
  839.                   { const,reg   }
  840.                   { const,const }
  841.                   { const,ref   }
  842.                    OPR_CONSTANT:
  843.                       case instr.operands[2].operandtype of
  844.                       { constant, constant does not have a specific size. }
  845.                         OPR_CONSTANT:
  846.                            p^.concat(new(pai68k,op_const_const(instruc,
  847.                            S_NO,operands[1].val,operands[2].val)));
  848.                         OPR_REFERENCE:
  849.                            Begin
  850.                                  p^.concat(new(pai68k,op_const_ref(instruc,
  851.                                  stropsize,operands[1].val,
  852.                                  newreference(operands[2].ref))))
  853.                            end;
  854.                         OPR_REGISTER:
  855.                            Begin
  856.                                  p^.concat(new(pai68k,op_const_reg(instruc,
  857.                                  stropsize,operands[1].val,
  858.                                  operands[2].reg)))
  859.                            end;
  860.                       else
  861.                          Begin
  862.                            Message(assem_f_internal_error_in_concatopcode);
  863.                          end;
  864.                       end; { end case }
  865.                    { ref,reg     }
  866.                    { ref,ref     }
  867.                    OPR_REFERENCE:
  868.                       case instr.operands[2].operandtype of
  869.                          OPR_REGISTER:
  870.                             Begin
  871.                               p^.concat(new(pai68k,op_ref_reg(instruc,
  872.                                stropsize,newreference(operands[1].ref),
  873.                                operands[2].reg)));
  874.                             end;
  875.                          OPR_REGLIST:
  876.                             Begin
  877.                               p^.concat(new(pai68k,op_ref_reglist(instruc,
  878.                                stropsize,newreference(operands[1].ref),
  879.                                operands[2].list)));
  880.                             end;
  881.                          OPR_REFERENCE: { special opcodes }
  882.                             p^.concat(new(pai68k,op_ref_ref(instruc,
  883.                             stropsize,newreference(operands[1].ref),
  884.                             newreference(operands[2].ref))));
  885.                       else
  886.                          Begin
  887.                            Message(assem_f_internal_error_in_concatopcode);
  888.                          end;
  889.                    end; { end inner case }
  890.                   end; { end case }
  891.                 end; { end with }
  892.         end;
  893.      3: Begin
  894.            if (instruc = A_DIVSL) or (instruc = A_DIVUL) or (instruc = A_MULU)
  895.            or (instruc = A_MULS) or (instruc = A_DIVS) or (instruc = A_DIVU) then
  896.            Begin
  897.              if (instr.operands[1].operandtype <> OPR_REGISTER)
  898.              or (instr.operands[2].operandtype <> OPR_REGISTER)
  899.              or (instr.operands[3].operandtype <> OPR_REGISTER) then
  900.              Begin
  901.                Message(assem_f_internal_error_in_concatopcode);
  902.              end
  903.              else
  904.              Begin
  905.                p^.concat(new(pai68k, op_reg_reg_reg(instruc,instr.stropsize,
  906.                  instr.operands[1].reg,instr.operands[2].reg,instr.operands[3].reg)));
  907.              end;
  908.            end
  909.            else
  910.             Message(assem_e_unsupported_opcode);
  911.         end;
  912.   end; { end case }
  913.  end;
  914.  end;
  915.  
  916.  
  917.     Procedure ConcatLabeledInstr(var instr: TInstruction);
  918.     Begin
  919.        if ((instr.getinstruction >= A_BCC) and (instr.getinstruction <= A_BVS))
  920.        or (instr.getinstruction = A_BRA) or (instr.getinstruction = A_BSR)
  921.        or (instr.getinstruction = A_JMP) or (instr.getinstruction = A_JSR)
  922.        or ((instr.getinstruction >= A_FBEQ) and (instr.getinstruction <= A_FBNGLE))
  923.        then
  924.        Begin
  925.         if instr.numops > 2 then
  926.           Message(assem_e_invalid_opcode)
  927.         else if instr.operands[1].operandtype <> OPR_LABINSTR then
  928.           Message(assem_e_invalid_opcode)
  929.         else if (instr.operands[1].operandtype = OPR_LABINSTR) and
  930.          (instr.numops = 1) then
  931.            if assigned(instr.operands[1].hl) then
  932.             ConcatLabel(p,instr.getinstruction, instr.operands[1].hl)
  933.            else
  934.             Message(assem_f_internal_error_in_findtype);
  935.        end
  936.        else
  937.        if ((instr.getinstruction >= A_DBCC) and (instr.getinstruction <= A_DBF))
  938.        or ((instr.getinstruction >= A_FDBEQ) and (instr.getinstruction <= A_FBDNGLE)) then
  939.        begin
  940.          p^.concat(new(pai_labeled,init_reg(instr.getinstruction,instr.operands[2].hl,
  941.            instr.operands[1].reg)));
  942.        end
  943.        else
  944.         Message(assem_e_invalid_operand);
  945.     end;
  946.  
  947.  
  948.  
  949.  
  950.  
  951.     Function BuildExpression: longint;
  952.   {*********************************************************************}
  953.   { FUNCTION BuildExpression: longint                                   }
  954.   {  Description: This routine calculates a constant expression to      }
  955.   {  a given value. The return value is the value calculated from       }
  956.   {  the expression.                                                    }
  957.   { The following tokens (not strings) are recognized:                  }
  958.   {    (,),SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants.  }
  959.   {*********************************************************************}
  960.   { ENTRY: On entry the token should be any valid expression token.     }
  961.   { EXIT:  On Exit the token points to either COMMA or SEPARATOR        }
  962.   { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  963.   {  invalid tokens.                                                    }
  964.   {*********************************************************************}
  965.   var expr: string;
  966.       tempstr: string;
  967.       l : longint;
  968.       errorflag: boolean;
  969.   Begin
  970.     errorflag := FALSE;
  971.     expr := '';
  972.     tempstr := '';
  973.     Repeat
  974.       Case actasmtoken of
  975.       AS_LPAREN: Begin
  976.                   Consume(AS_LPAREN);
  977.                   expr := expr + '(';
  978.                 end;
  979.       AS_RPAREN: Begin
  980.                   Consume(AS_RPAREN);
  981.                   expr := expr + ')';
  982.                 end;
  983.       AS_SHL:    Begin
  984.                   Consume(AS_SHL);
  985.                   expr := expr + '<';
  986.                 end;
  987.       AS_SHR:    Begin
  988.                   Consume(AS_SHR);
  989.                   expr := expr + '>';
  990.                 end;
  991.       AS_SLASH:  Begin
  992.                   Consume(AS_SLASH);
  993.                   expr := expr + '/';
  994.                 end;
  995.       AS_MOD:    Begin
  996.                   Consume(AS_MOD);
  997.                   expr := expr + '%';
  998.                 end;
  999.       AS_STAR:   Begin
  1000.                   Consume(AS_STAR);
  1001.                   expr := expr + '*';
  1002.                 end;
  1003.       AS_PLUS:   Begin
  1004.                   Consume(AS_PLUS);
  1005.                   expr := expr + '+';
  1006.                 end;
  1007.       AS_MINUS:  Begin
  1008.                   Consume(AS_MINUS);
  1009.                   expr := expr + '-';
  1010.                 end;
  1011.       AS_AND:    Begin
  1012.                   Consume(AS_AND);
  1013.                   expr := expr + '&';
  1014.                 end;
  1015.       AS_NOT:    Begin
  1016.                   Consume(AS_NOT);
  1017.                   expr := expr + '~';
  1018.                 end;
  1019.       AS_XOR:    Begin
  1020.                   Consume(AS_XOR);
  1021.                   expr := expr + '^';
  1022.                 end;
  1023.       AS_OR:     Begin
  1024.                   Consume(AS_OR);
  1025.                   expr := expr + '|';
  1026.                 end;
  1027.       AS_ID:    Begin
  1028.                   if NOT SearchIConstant(actasmpattern,l) then
  1029.                   Begin
  1030.                     Message1(assem_e_invalid_const_symbol,actasmpattern);
  1031.                     l := 0;
  1032.                   end;
  1033.                   str(l, tempstr);
  1034.                   expr := expr + tempstr;
  1035.                   Consume(AS_ID);
  1036.                 end;
  1037.       AS_INTNUM:  Begin
  1038.                    expr := expr + actasmpattern;
  1039.                    Consume(AS_INTNUM);
  1040.                  end;
  1041.       AS_BINNUM:  Begin
  1042.                       tempstr := BinaryToDec(actasmpattern);
  1043.                       if tempstr = '' then
  1044.                        Message(assem_f_error_converting_bin);
  1045.                       expr:=expr+tempstr;
  1046.                       Consume(AS_BINNUM);
  1047.                  end;
  1048.  
  1049.       AS_HEXNUM: Begin
  1050.                     tempstr := HexToDec(actasmpattern);
  1051.                     if tempstr = '' then
  1052.                      Message(assem_f_error_converting_hex);
  1053.                     expr:=expr+tempstr;
  1054.                     Consume(AS_HEXNUM);
  1055.                 end;
  1056.       AS_OCTALNUM: Begin
  1057.                     tempstr := OctalToDec(actasmpattern);
  1058.                     if tempstr = '' then
  1059.                      Message(assem_f_error_converting_octal);
  1060.                     expr:=expr+tempstr;
  1061.                     Consume(AS_OCTALNUM);
  1062.                   end;
  1063.       { go to next term }
  1064.       AS_COMMA: Begin
  1065.                   if not ErrorFlag then
  1066.                     BuildExpression := CalculateExpression(expr)
  1067.                   else
  1068.                     BuildExpression := 0;
  1069.                   Exit;
  1070.                end;
  1071.       { go to next symbol }
  1072.       AS_SEPARATOR: Begin
  1073.                       if not ErrorFlag then
  1074.                         BuildExpression := CalculateExpression(expr)
  1075.                       else
  1076.                         BuildExpression := 0;
  1077.                       Exit;
  1078.                    end;
  1079.       else
  1080.         Begin
  1081.           { only write error once. }
  1082.           if not errorflag then
  1083.            Message(assem_e_invalid_constant_expression);
  1084.           { consume tokens until we find COMMA or SEPARATOR }
  1085.           Consume(actasmtoken);
  1086.           errorflag := TRUE;
  1087.         End;
  1088.       end;
  1089.     Until false;
  1090.   end;
  1091.  
  1092.  
  1093.   Procedure BuildRealConstant(typ : tfloattype);
  1094.   {*********************************************************************}
  1095.   { PROCEDURE BuilRealConst                                             }
  1096.   {  Description: This routine calculates a constant expression to      }
  1097.   {  a given value. The return value is the value calculated from       }
  1098.   {  the expression.                                                    }
  1099.   { The following tokens (not strings) are recognized:                  }
  1100.   {    +/-,numbers and real numbers                                     }
  1101.   {*********************************************************************}
  1102.   { ENTRY: On entry the token should be any valid expression token.     }
  1103.   { EXIT:  On Exit the token points to either COMMA or SEPARATOR        }
  1104.   { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  1105.   {  invalid tokens.                                                    }
  1106.   {*********************************************************************}
  1107.   var expr: string;
  1108.       tempstr: string;
  1109.       r : extended;
  1110.       code : word;
  1111.       negativ : boolean;
  1112.       errorflag: boolean;
  1113.   Begin
  1114.     errorflag := FALSE;
  1115.     Repeat
  1116.     negativ:=false;
  1117.     expr := '';
  1118.     tempstr := '';
  1119.     if actasmtoken=AS_PLUS then Consume(AS_PLUS)
  1120.     else if actasmtoken=AS_MINUS then
  1121.       begin
  1122.          negativ:=true;
  1123.          consume(AS_MINUS);
  1124.       end;
  1125.     Case actasmtoken of
  1126.       AS_INTNUM:  Begin
  1127.                    expr := actasmpattern;
  1128.                    Consume(AS_INTNUM);
  1129.                  end;
  1130.       AS_REALNUM:  Begin
  1131.                    expr := actasmpattern;
  1132.                    { in ATT syntax you have 0d in front of the real }
  1133.                    { should this be forced ?  yes i think so, as to }
  1134.                    { conform to gas as much as possible.            }
  1135.                    if (expr[1]='0') and (upper(expr[2])='D') then
  1136.                      expr:=copy(expr,3,255);
  1137.                    Consume(AS_REALNUM);
  1138.                  end;
  1139.       AS_BINNUM:  Begin
  1140.                       { checking for real constants with this should use  }
  1141.                       { real DECODING otherwise the compiler will crash!  }
  1142.                       Message(assem_w_float_bin_ignored);
  1143.                       Consume(AS_BINNUM);
  1144.                  end;
  1145.  
  1146.       AS_HEXNUM: Begin
  1147.                       { checking for real constants with this should use  }
  1148.                       { real DECODING otherwise the compiler will crash!  }
  1149.                     Message(assem_w_float_hex_ignored);
  1150.                     Consume(AS_HEXNUM);
  1151.                 end;
  1152.       AS_OCTALNUM: Begin
  1153.                       { checking for real constants with this should use    }
  1154.                       { real DECODING otherwise the compiler will crash!    }
  1155.                       { xxxToDec using reals could be a solution, but the   }
  1156.                       { problem is that these will crash the m68k compiler  }
  1157.                       { when compiling -- because of lack of good fpu       }
  1158.                       { support.                                           }
  1159.                     Message(assem_w_float_octal_ignored);
  1160.                     Consume(AS_OCTALNUM);
  1161.                   end;
  1162.          else
  1163.            Begin
  1164.              { only write error once. }
  1165.              if not errorflag then
  1166.               Message(assem_e_invalid_real_const);
  1167.              { consume tokens until we find COMMA or SEPARATOR }
  1168.              Consume(actasmtoken);
  1169.              errorflag := TRUE;
  1170.            End;
  1171.  
  1172.          end;
  1173.       { go to next term }
  1174.       if (actasmtoken=AS_COMMA) or (actasmtoken=AS_SEPARATOR) then
  1175.         Begin
  1176.           if negativ then expr:='-'+expr;
  1177.           val(expr,r,code);
  1178.           if code<>0 then
  1179.             Begin
  1180.                r:=0;
  1181.                Message(assem_e_invalid_real_const);
  1182.                ConcatRealConstant(p,r,typ);
  1183.             End
  1184.           else
  1185.             Begin
  1186.               ConcatRealConstant(p,r,typ);
  1187.             End;
  1188.         end
  1189.       else
  1190.         Message(assem_e_invalid_real_const);
  1191.     Until actasmtoken=AS_SEPARATOR;
  1192.   end;
  1193.  
  1194.  
  1195.  
  1196.   Procedure BuildScaling(Var instr: TInstruction);
  1197.   {*********************************************************************}
  1198.   {  Takes care of parsing expression starting from the scaling value   }
  1199.   {  up to and including possible field specifiers.                     }
  1200.   { EXIT CONDITION:  On exit the routine should point to  AS_SEPARATOR  }
  1201.   { or AS_COMMA. On entry should point to the AS_STAR  token.           }
  1202.   {*********************************************************************}
  1203.   var str:string;
  1204.       l: longint;
  1205.       code: integer;
  1206.   Begin
  1207.      Consume(AS_STAR);
  1208.      if (instr.operands[operandnum].ref.scalefactor <> 0)
  1209.      and (instr.operands[operandnum].ref.scalefactor <> 1) then
  1210.       Message(assem_f_internal_error_in_buildscale);
  1211.      case actasmtoken of
  1212.         AS_INTNUM: str := actasmpattern;
  1213.         AS_HEXNUM: str := HexToDec(actasmpattern);
  1214.         AS_BINNUM: str := BinaryToDec(actasmpattern);
  1215.         AS_OCTALNUM: str := OctalToDec(actasmpattern);
  1216.      else
  1217.         Message(assem_e_syntax_error);
  1218.      end;
  1219.      val(str, l, code);
  1220.      if code <> 0 then
  1221.       Message(assem_e_invalid_scaling_factor);
  1222.      if ((l = 2) or (l = 4) or (l = 8) or (l = 1)) and (code = 0) then
  1223.      begin
  1224.         instr.operands[operandnum].ref.scalefactor := l;
  1225.      end
  1226.      else
  1227.      Begin
  1228.         Message(assem_e_invalid_scaling_value);
  1229.         instr.operands[operandnum].ref.scalefactor := 0;
  1230.      end;
  1231.      if instr.operands[operandnum].ref.index = R_NO then
  1232.      Begin
  1233.         Message(assem_e_scaling_value_only_allowed_with_index);
  1234.         instr.operands[operandnum].ref.scalefactor := 0;
  1235.      end;
  1236.     { Consume the scaling number }
  1237.     Consume(actasmtoken);
  1238.     if actasmtoken = AS_RPAREN then
  1239.         Consume(AS_RPAREN)
  1240.     else
  1241.        Message(assem_e_invalid_scaling_value);
  1242.     { // .Field.Field ... or separator/comma // }
  1243.     if actasmtoken in [AS_COMMA,AS_SEPARATOR] then
  1244.     Begin
  1245.     end
  1246.     else
  1247.      Message(assem_e_syntax_error);
  1248.   end;
  1249.  
  1250.  
  1251.   Function BuildRefExpression: longint;
  1252.   {*********************************************************************}
  1253.   { FUNCTION BuildExpression: longint                                   }
  1254.   {  Description: This routine calculates a constant expression to      }
  1255.   {  a given value. The return value is the value calculated from       }
  1256.   {  the expression.                                                    }
  1257.   { The following tokens (not strings) are recognized:                  }
  1258.   {    SHL,SHR,/,*,NOT,OR,XOR,AND,MOD,+/-,numbers,ID to constants.      }
  1259.   {*********************************************************************}
  1260.   { ENTRY: On entry the token should be any valid expression token.     }
  1261.   { EXIT:  On Exit the token points to the LPAREN token.                }
  1262.   { ERROR RECOVERY: Tries to find COMMA or SEPARATOR token by consuming }
  1263.   {  invalid tokens.                                                    }
  1264.   {*********************************************************************}
  1265.   var tempstr: string;
  1266.       expr: string;
  1267.     l : longint;
  1268.     errorflag : boolean;
  1269.   Begin
  1270.     errorflag := FALSE;
  1271.     tempstr := '';
  1272.     expr := '';
  1273.     Repeat
  1274.       Case actasmtoken of
  1275.       AS_RPAREN: Begin
  1276.                    Message(assem_e_parenthesis_are_not_allowed);
  1277.                   Consume(AS_RPAREN);
  1278.                 end;
  1279.       AS_SHL:    Begin
  1280.                   Consume(AS_SHL);
  1281.                   expr := expr + '<';
  1282.                 end;
  1283.       AS_SHR:    Begin
  1284.                   Consume(AS_SHR);
  1285.                   expr := expr + '>';
  1286.                 end;
  1287.       AS_SLASH:  Begin
  1288.                   Consume(AS_SLASH);
  1289.                   expr := expr + '/';
  1290.                 end;
  1291.       AS_MOD:    Begin
  1292.                   Consume(AS_MOD);
  1293.                   expr := expr + '%';
  1294.                 end;
  1295.       AS_STAR:   Begin
  1296.                   Consume(AS_STAR);
  1297.                   expr := expr + '*';
  1298.                 end;
  1299.       AS_PLUS:   Begin
  1300.                   Consume(AS_PLUS);
  1301.                   expr := expr + '+';
  1302.                 end;
  1303.       AS_MINUS:  Begin
  1304.                   Consume(AS_MINUS);
  1305.                   expr := expr + '-';
  1306.                 end;
  1307.       AS_AND:    Begin
  1308.                   Consume(AS_AND);
  1309.                   expr := expr + '&';
  1310.                 end;
  1311.       AS_NOT:    Begin
  1312.                   Consume(AS_NOT);
  1313.                   expr := expr + '~';
  1314.                 end;
  1315.       AS_XOR:    Begin
  1316.                   Consume(AS_XOR);
  1317.                   expr := expr + '^';
  1318.                 end;
  1319.       AS_OR:     Begin
  1320.                   Consume(AS_OR);
  1321.                   expr := expr + '|';
  1322.                 end;
  1323.       { End of reference }
  1324.       AS_LPAREN: Begin
  1325.                      if not ErrorFlag then
  1326.                         BuildRefExpression := CalculateExpression(expr)
  1327.                      else
  1328.                         BuildRefExpression := 0;
  1329.                      { no longer in an expression }
  1330.                      exit;
  1331.                   end;
  1332.       AS_ID:
  1333.                 Begin
  1334.                   if NOT SearchIConstant(actasmpattern,l) then
  1335.                   Begin
  1336.                     Message1(assem_e_invalid_const_symbol,actasmpattern);
  1337.                     l := 0;
  1338.                   end;
  1339.                   str(l, tempstr);
  1340.                   expr := expr + tempstr;
  1341.                   Consume(AS_ID);
  1342.                 end;
  1343.       AS_INTNUM:  Begin
  1344.                    expr := expr + actasmpattern;
  1345.                    Consume(AS_INTNUM);
  1346.                  end;
  1347.       AS_BINNUM:  Begin
  1348.                       tempstr := BinaryToDec(actasmpattern);
  1349.                       if tempstr = '' then
  1350.                        Message(assem_f_error_converting_bin);
  1351.                       expr:=expr+tempstr;
  1352.                       Consume(AS_BINNUM);
  1353.                  end;
  1354.  
  1355.       AS_HEXNUM: Begin
  1356.                     tempstr := HexToDec(actasmpattern);
  1357.                     if tempstr = '' then
  1358.                      Message(assem_f_error_converting_hex);
  1359.                     expr:=expr+tempstr;
  1360.                     Consume(AS_HEXNUM);
  1361.                 end;
  1362.       AS_OCTALNUM: Begin
  1363.                     tempstr := OctalToDec(actasmpattern);
  1364.                     if tempstr = '' then
  1365.                      Message(assem_f_error_converting_octal);
  1366.                     expr:=expr+tempstr;
  1367.                     Consume(AS_OCTALNUM);
  1368.                   end;
  1369.       else
  1370.         Begin
  1371.           { write error only once. }
  1372.           if not errorflag then
  1373.            Message(assem_e_invalid_constant_expression);
  1374.           BuildRefExpression := 0;
  1375.           if actasmtoken in [AS_COMMA,AS_SEPARATOR] then exit;
  1376.           { consume tokens until we find COMMA or SEPARATOR }
  1377.           Consume(actasmtoken);
  1378.           errorflag := TRUE;
  1379.         end;
  1380.       end;
  1381.     Until false;
  1382.   end;
  1383.  
  1384.  
  1385.   Procedure BuildReference(var Instr: TInstruction);
  1386.   {*********************************************************************}
  1387.   { PROCEDURE BuildBracketExpression                                    }
  1388.   {  Description: This routine builds up an expression after a LPAREN   }
  1389.   {  token is encountered.                                              }
  1390.   {   On entry actasmtoken should be equal to AS_LPAREN                 }
  1391.   {*********************************************************************}
  1392.   { EXIT CONDITION:  On exit the routine should point to either the     }
  1393.   {       AS_COMMA or AS_SEPARATOR token.                               }
  1394.   {*********************************************************************}
  1395.   var
  1396.     l:longint;
  1397.     code: integer;
  1398.     str: string;
  1399.   Begin
  1400.      Consume(AS_LPAREN);
  1401.      Case actasmtoken of
  1402.         { // (reg ... // }
  1403.         AS_REGISTER: Begin
  1404.                         instr.operands[operandnum].ref.base :=
  1405.                            findregister(actasmpattern);
  1406.                         Consume(AS_REGISTER);
  1407.                         { can either be a register or a right parenthesis }
  1408.                          { // (reg)       // }
  1409.                          { // (reg)+      // }
  1410.                          if actasmtoken=AS_RPAREN then
  1411.                          Begin
  1412.                            Consume(AS_RPAREN);
  1413.                            if actasmtoken = AS_PLUS then
  1414.                            Begin
  1415.                              if (instr.operands[operandnum].ref.direction <> dir_none) then
  1416.                               Message(assem_e_no_inc_and_dec_together)
  1417.                              else
  1418.                                instr.operands[operandnum].ref.direction := dir_inc;
  1419.                              Consume(AS_PLUS);
  1420.                            end;
  1421.                            if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  1422.                              Begin
  1423.                                Message(assem_e_invalid_reference);
  1424.                                { error recovery ... }
  1425.                                while actasmtoken <> AS_SEPARATOR do
  1426.                                   Consume(actasmtoken);
  1427.                              end;
  1428.                              exit;
  1429.                          end;
  1430.                        { // (reg,reg .. // }
  1431.                        Consume(AS_COMMA);
  1432.                        if actasmtoken = AS_REGISTER then
  1433.                        Begin
  1434.                          instr.operands[operandnum].ref.index :=
  1435.                            findregister(actasmpattern);
  1436.                          Consume(AS_REGISTER);
  1437.                          { check for scaling ... }
  1438.                          case actasmtoken of
  1439.                            AS_RPAREN:
  1440.                               Begin
  1441.                                 Consume(AS_RPAREN);
  1442.                                 if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  1443.                                 Begin
  1444.                                 { error recovery ... }
  1445.                                   Message(assem_e_invalid_reference);
  1446.                                   while actasmtoken <> AS_SEPARATOR do
  1447.                                     Consume(actasmtoken);
  1448.                                 end;
  1449.                                 exit;
  1450.                               end;
  1451.                            AS_STAR:
  1452.                               Begin
  1453.                                 BuildScaling(instr);
  1454.                               end;
  1455.                          else
  1456.                            Begin
  1457.                              Message(assem_e_invalid_reference_syntax);
  1458.                              while (actasmtoken <> AS_SEPARATOR) do
  1459.                                Consume(actasmtoken);
  1460.                            end;
  1461.                          end; { end case }
  1462.                        end
  1463.                        else
  1464.                           Begin
  1465.                              Message(assem_e_invalid_reference_syntax);
  1466.                             while (actasmtoken <> AS_SEPARATOR) do
  1467.                                 Consume(actasmtoken);
  1468.                           end;
  1469.                      end;
  1470.        AS_HEXNUM,AS_OCTALNUM,   { direct address }
  1471.        AS_BINNUM,AS_INTNUM: Begin
  1472.                                 case actasmtoken of
  1473.                                         AS_INTNUM: str := actasmpattern;
  1474.                                         AS_HEXNUM: str := HexToDec(actasmpattern);
  1475.                                         AS_BINNUM: str := BinaryToDec(actasmpattern);
  1476.                                         AS_OCTALNUM: str := OctalToDec(actasmpattern);
  1477.                                 else
  1478.                                         Message(assem_e_syntax_error);
  1479.                                 end;
  1480.                                 Consume(actasmtoken);
  1481.                                 val(str, l, code);
  1482.                                 if code <> 0 then
  1483.                                      Message(assem_e_invalid_reference_syntax)
  1484.                                 else
  1485.                                      instr.operands[operandnum].ref.offset := l;
  1486.                                 Consume(AS_RPAREN);
  1487.                                 if not (actasmtoken in [AS_COMMA,AS_SEPARATOR]) then
  1488.                                 Begin
  1489.                                       { error recovery ... }
  1490.                                       Message(assem_e_invalid_reference);
  1491.                                       while actasmtoken <> AS_SEPARATOR do
  1492.                                         Consume(actasmtoken);
  1493.                                 end;
  1494.                                 exit;
  1495.                             end;
  1496.      else
  1497.        Begin
  1498.  
  1499.          Message(assem_e_invalid_reference_syntax);
  1500.          while (actasmtoken <> AS_SEPARATOR) do
  1501.            Consume(actasmtoken);
  1502.        end;
  1503.      end; { end case }
  1504.   end;
  1505.  
  1506.  
  1507.   Procedure BuildOperand(var instr: TInstruction);
  1508.   {*********************************************************************}
  1509.   { EXIT CONDITION:  On exit the routine should point to either the     }
  1510.   {       AS_COMMA or AS_SEPARATOR token.                               }
  1511.   {*********************************************************************}
  1512.   var
  1513.     tempstr: string;
  1514.     expr: string;
  1515.     lab: Pasmlabel;
  1516.     l : longint;
  1517.     i: tregister;
  1518.     hl: plabel;
  1519.     reg_one, reg_two: tregister;
  1520.     reglist: set of tregister;
  1521.   Begin
  1522.    reglist := [];
  1523.    tempstr := '';
  1524.    expr := '';
  1525.    case actasmtoken of
  1526.    { // Memory reference //  }
  1527.      AS_LPAREN:
  1528.                Begin
  1529.                   initAsmRef(instr);
  1530.                   BuildReference(instr);
  1531.                end;
  1532.    { // Constant expression //  }
  1533.      AS_APPT:  Begin
  1534.                       Consume(AS_APPT);
  1535.                       if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_CONSTANT]) then
  1536.                          Message(assem_e_invalid_operand_type);
  1537.                       { identifiers are handled by BuildExpression }
  1538.                       instr.operands[operandnum].operandtype := OPR_CONSTANT;
  1539.                       instr.operands[operandnum].val :=BuildExpression;
  1540.                  end;
  1541.    { // Constant memory offset .              // }
  1542.    { // This must absolutely be followed by ( // }
  1543.      AS_HEXNUM,AS_INTNUM,
  1544.      AS_BINNUM,AS_OCTALNUM,AS_PLUS:
  1545.                    Begin
  1546.                       InitAsmRef(instr);
  1547.                       instr.operands[operandnum].ref.offset:=BuildRefExpression;
  1548.                       BuildReference(instr);
  1549.                    end;
  1550.    { // A constant expression, or a Variable ref. // }
  1551.      AS_ID:  Begin
  1552.               if actasmpattern[1] = '@' then
  1553.               { // Label or Special symbol reference // }
  1554.               Begin
  1555.                  if actasmpattern = '@RESULT' then
  1556.                    Begin
  1557.                       InitAsmRef(instr);
  1558.                       SetUpResult(instr,operandnum);
  1559.                    end
  1560.                  else
  1561.                   if (actasmpattern = '@CODE') or (actasmpattern = '@DATA') then
  1562.                     Message(assem_w_CODE_and_DATA_not_supported)
  1563.                    else
  1564.                   Begin
  1565.                     delete(actasmpattern,1,1);
  1566.                     if actasmpattern = '' then
  1567.                      Message(assem_e_null_label_ref_not_allowed);
  1568.                     lab := labellist.search(actasmpattern);
  1569.                     { check if the label is already defined   }
  1570.                     { if so, we then check if the plabel is   }
  1571.                     { non-nil, if so we add it to instruction }
  1572.                     if assigned(lab) then
  1573.                      Begin
  1574.                      if assigned(lab^.lab) then
  1575.                        Begin
  1576.                          instr.operands[operandnum].operandtype := OPR_LABINSTR;
  1577.                          instr.operands[operandnum].hl := lab^.lab;
  1578.                          instr.labeled := TRUE;
  1579.                        end;
  1580.                      end
  1581.                     else
  1582.                     { the label does not exist, create it }
  1583.                     { emit the opcode, but set that the   }
  1584.                     { label has not been emitted          }
  1585.                      Begin
  1586.                         getlabel(hl);
  1587.                         labellist.insert(actasmpattern,hl,FALSE);
  1588.                         instr.operands[operandnum].operandtype := OPR_LABINSTR;
  1589.                         instr.operands[operandnum].hl := hl;
  1590.                         instr.labeled := TRUE;
  1591.                      end;
  1592.                   end;
  1593.                 Consume(AS_ID);
  1594.                 if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1595.                  Message(assem_e_syntax_error);
  1596.               end
  1597.               { probably a variable or normal expression }
  1598.               { or a procedure (such as in CALL ID)      }
  1599.               else
  1600.                Begin
  1601.                    { is it a constant ? }
  1602.                    if SearchIConstant(actasmpattern,l) then
  1603.                    Begin
  1604.                       InitAsmRef(instr);
  1605.                       instr.operands[operandnum].ref.offset:=BuildRefExpression;
  1606.                       BuildReference(instr);
  1607.  
  1608. {                      if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_CONSTANT]) then
  1609.                         Message(assem_e_invalid_operand_type);
  1610.                       instr.operands[operandnum].operandtype := OPR_CONSTANT;
  1611.                       instr.operands[operandnum].val :=BuildExpression;}
  1612.                     end
  1613.                    else { is it a label variable ? }
  1614.                     Begin
  1615.                      { // ID[ , ID.Field.Field or simple ID // }
  1616.                      { check if this is a label, if so then }
  1617.                      { emit it as a label.                  }
  1618.                      if SearchLabel(actasmpattern,hl) then
  1619.                      Begin
  1620.                         instr.operands[operandnum].operandtype := OPR_LABINSTR;
  1621.                         instr.operands[operandnum].hl := hl;
  1622.                         instr.labeled := TRUE;
  1623.                         Consume(AS_ID);
  1624.                         if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1625.                          Message(assem_e_syntax_error);
  1626.                      end
  1627.                      else
  1628.                      { is it a normal variable ? }
  1629.                      Begin
  1630.                       initAsmRef(instr);
  1631.                       if not CreateVarInstr(instr,actasmpattern,operandnum) then
  1632.                       Begin
  1633.                          { not a variable.. }
  1634.                          { check special variables.. }
  1635.                          if actasmpattern = 'SELF' then
  1636.                           { special self variable }
  1637.                          Begin
  1638.                            if assigned(procinfo._class) then
  1639.                              Begin
  1640.                                instr.operands[operandnum].ref.offset := procinfo.ESI_offset;
  1641.                                instr.operands[operandnum].ref.base := procinfo.framepointer;
  1642.                              end
  1643.                            else
  1644.                              Message(assem_e_cannot_use_SELF_outside_a_method);
  1645.                          end
  1646.                          else
  1647.                          if (cs_compilesystem in aktswitches) then
  1648.                          Begin
  1649.                            if not assigned(instr.operands[operandnum].ref.symbol) then
  1650.                            Begin
  1651.                              instr.operands[operandnum].ref.symbol:=newpasstr(actasmpattern);
  1652.                              Message1(assem_w_id_supposed_external,actasmpattern);
  1653.                            end;
  1654.                          end
  1655.                          else
  1656.                            Message1(assem_e_unknown_id,actasmpattern);
  1657.                       end;
  1658.                       expr := actasmpattern;
  1659.                       Consume(AS_ID);
  1660.                       case actasmtoken of
  1661.                            AS_LPAREN: { indexing }
  1662.                                         BuildReference(instr);
  1663.                            AS_SEPARATOR,AS_COMMA: ;
  1664.                       else
  1665.                            Message(assem_e_syntax_error);
  1666.                       end;
  1667.                      end;
  1668.                     end;
  1669.                end;
  1670.             end;
  1671.    { // Pre-decrement mode reference or constant mem offset.   // }
  1672.      AS_MINUS:    Begin
  1673.                    Consume(AS_MINUS);
  1674.                    if actasmtoken = AS_LPAREN then
  1675.                    Begin
  1676.                      InitAsmRef(instr);
  1677.                      { indicate pre-decrement mode }
  1678.                      instr.operands[operandnum].ref.direction := dir_dec;
  1679.                      BuildReference(instr);
  1680.                    end
  1681.                    else
  1682.                    if actasmtoken in [AS_OCTALNUM,AS_HEXNUM,AS_BINNUM,AS_INTNUM] then
  1683.                    Begin
  1684.                       InitAsmRef(instr);
  1685.                       instr.operands[operandnum].ref.offset:=BuildRefExpression;
  1686.                       { negate because was preceded by a negative sign! }
  1687.                       instr.operands[operandnum].ref.offset:=-instr.operands[operandnum].ref.offset;
  1688.                       BuildReference(instr);
  1689.                    end
  1690.                    else
  1691.                    Begin
  1692.                     Message(assem_e_syntax_error);
  1693.                     while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1694.                        Consume(actasmtoken);
  1695.                    end;
  1696.                   end;
  1697.    { // Register, a variable reference or a constant reference // }
  1698.      AS_REGISTER: Begin
  1699.                    { save the type of register used. }
  1700.                    tempstr := actasmpattern;
  1701.                    Consume(AS_REGISTER);
  1702.                    { // Simple register // }
  1703.                    if (actasmtoken = AS_SEPARATOR) or (actasmtoken = AS_COMMA) then
  1704.                    Begin
  1705.                         if not (instr.operands[operandnum].operandtype in [OPR_NONE,OPR_REGISTER]) then
  1706.                          Message(assem_e_invalid_operand_type);
  1707.                         instr.operands[operandnum].operandtype := OPR_REGISTER;
  1708.                         instr.operands[operandnum].reg := findregister(tempstr);
  1709.                    end
  1710.                    else
  1711.                    { HERE WE MUST HANDLE THE SPECIAL CASE OF MOVEM AND FMOVEM }
  1712.                    { // Individual register listing // }
  1713.                    if (actasmtoken = AS_SLASH) then
  1714.                    Begin
  1715.                      reglist := [findregister(tempstr)];
  1716.                      Consume(AS_SLASH);
  1717.                      if actasmtoken = AS_REGISTER then
  1718.                      Begin
  1719.                        While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1720.                        Begin
  1721.                          case actasmtoken of
  1722.                           AS_REGISTER: Begin
  1723.                                         reglist := reglist + [findregister(actasmpattern)];
  1724.                                         Consume(AS_REGISTER);
  1725.                                        end;
  1726.                           AS_SLASH: Consume(AS_SLASH);
  1727.                           AS_SEPARATOR,AS_COMMA: break;
  1728.                          else
  1729.                           Begin
  1730.                             Message(assem_e_invalid_reg_list_in_movem);
  1731.                             Consume(actasmtoken);
  1732.                           end;
  1733.                          end; { end case }
  1734.                        end; { end while }
  1735.                        instr.operands[operandnum].operandtype:= OPR_REGLIST;
  1736.                        instr.operands[operandnum].list := reglist;
  1737.                      end
  1738.                      else
  1739.                       { error recovery ... }
  1740.                       Begin
  1741.                             Message(assem_e_invalid_reg_list_in_movem);
  1742.                             while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1743.                                Consume(actasmtoken);
  1744.                       end;
  1745.                    end
  1746.                    else
  1747.                    { // Range register listing // }
  1748.                    if (actasmtoken = AS_MINUS) then
  1749.                    Begin
  1750.                      Consume(AS_MINUS);
  1751.                      reg_one:=findregister(tempstr);
  1752.                      if actasmtoken <> AS_REGISTER then
  1753.                      Begin
  1754.                        Message(assem_e_invalid_reg_list_in_movem);
  1755.                        while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1756.                          Consume(actasmtoken);
  1757.                      end
  1758.                      else
  1759.                      Begin
  1760.                       { determine the register range ... }
  1761.                       reg_two:=findregister(actasmpattern);
  1762.                       if reg_one > reg_two then
  1763.                       begin
  1764.                        for i:=reg_two to reg_one do
  1765.                          reglist := reglist + [i];
  1766.                       end
  1767.                       else
  1768.                       Begin
  1769.                        for i:=reg_one to reg_two do
  1770.                          reglist := reglist + [i];
  1771.                       end;
  1772.                       Consume(AS_REGISTER);
  1773.                       if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1774.                       Begin
  1775.                        Message(assem_e_invalid_reg_list_in_movem);
  1776.                        while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1777.                          Consume(actasmtoken);
  1778.                       end;
  1779.                       { set up instruction }
  1780.                       instr.operands[operandnum].operandtype:= OPR_REGLIST;
  1781.                       instr.operands[operandnum].list := reglist;
  1782.                      end;
  1783.                    end
  1784.                    else
  1785.                    { DIVSL/DIVS/MULS/MULU with long for MC68020 only }
  1786.                    if (actasmtoken = AS_COLON) then
  1787.                    Begin
  1788.                      if (opt_processors = MC68020) or (cs_compilesystem in aktswitches) then
  1789.                      Begin
  1790.                        Consume(AS_COLON);
  1791.                        if (actasmtoken = AS_REGISTER) then
  1792.                        Begin
  1793.                          { set up old field, since register is valid }
  1794.                          instr.operands[operandnum].operandtype := OPR_REGISTER;
  1795.                          instr.operands[operandnum].reg := findregister(tempstr);
  1796.                          Inc(operandnum);
  1797.                          instr.operands[operandnum].operandtype := OPR_REGISTER;
  1798.                          instr.operands[operandnum].reg := findregister(actasmpattern);
  1799.                          Consume(AS_REGISTER);
  1800.                          if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1801.                          Begin
  1802.                           Message(assem_e_invalid_reg_list_for_opcode);
  1803.                           while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1804.                             Consume(actasmtoken);
  1805.                          end;
  1806.                        end;
  1807.                      end
  1808.                      else
  1809.                      Begin
  1810.                         Message(assem_e_68020_mode_required);
  1811.                         if not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) then
  1812.                         Begin
  1813.                           Message(assem_e_invalid_reg_list_for_opcode);
  1814.                           while not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1815.                             Consume(actasmtoken);
  1816.                         end;
  1817.                      end;
  1818.                    end
  1819.                    else
  1820.                     Message1(assem_e_syn_register,tempstr);
  1821.                  end;
  1822.      AS_SEPARATOR, AS_COMMA: ;
  1823.     else
  1824.      Begin
  1825.       Message(assem_e_syn_opcode_operand);
  1826.       Consume(actasmtoken);
  1827.      end;
  1828.   end; { end case }
  1829.  end;
  1830.  
  1831.  
  1832.  
  1833.   Procedure BuildConstant(maxvalue: longint);
  1834.   {*********************************************************************}
  1835.   { PROCEDURE BuildConstant                                             }
  1836.   {  Description: This routine takes care of parsing a DB,DD,or DW      }
  1837.   {  line and adding those to the assembler node. Expressions, range-   }
  1838.   {  checking are fullly taken care of.                                 }
  1839.   {   maxvalue: $ff -> indicates that this is a DB node.                }
  1840.   {             $ffff -> indicates that this is a DW node.              }
  1841.   {             $ffffffff -> indicates that this is a DD node.          }
  1842.   {*********************************************************************}
  1843.   { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
  1844.   {*********************************************************************}
  1845.   var
  1846.    strlength: byte;
  1847.    expr: string;
  1848.    tempstr: string;
  1849.    value : longint;
  1850.   Begin
  1851.       Repeat
  1852.         Case actasmtoken of
  1853.           AS_STRING: Begin
  1854.                       if maxvalue = $ff then
  1855.                          strlength := 1
  1856.                       else
  1857.                          Message(assem_e_string_not_allowed_as_const);
  1858.                       expr := actasmpattern;
  1859.                       if length(expr) > 1 then
  1860.                        Message(assem_e_string_not_allowed_as_const);
  1861.                       Consume(AS_STRING);
  1862.                       Case actasmtoken of
  1863.                        AS_COMMA: Consume(AS_COMMA);
  1864.                        AS_SEPARATOR: ;
  1865.                       else
  1866.                        Message(assem_e_invalid_string_expression);
  1867.                       end; { end case }
  1868.                       ConcatString(p,expr);
  1869.                     end;
  1870.           AS_INTNUM,AS_BINNUM,
  1871.           AS_OCTALNUM,AS_HEXNUM:
  1872.                     Begin
  1873.                       value:=BuildExpression;
  1874.                       ConcatConstant(p,value,maxvalue);
  1875.                     end;
  1876.           AS_ID:
  1877.                      Begin
  1878.                       value:=BuildExpression;
  1879.                       if value > maxvalue then
  1880.                       Begin
  1881.                          Message(assem_e_constant_out_of_bounds);
  1882.                          { assuming a value of maxvalue }
  1883.                          value := maxvalue;
  1884.                       end;
  1885.                       ConcatConstant(p,value,maxvalue);
  1886.                   end;
  1887.           { These terms can start an assembler expression }
  1888.           AS_PLUS,AS_MINUS,AS_LPAREN,AS_NOT: Begin
  1889.                                           value := BuildExpression;
  1890.                                           ConcatConstant(p,value,maxvalue);
  1891.                                          end;
  1892.           AS_COMMA:  BEGIN
  1893.                        Consume(AS_COMMA);
  1894.                      END;
  1895.           AS_SEPARATOR: ;
  1896.  
  1897.         else
  1898.          Begin
  1899.            Message(assem_f_internal_error_in_buildconstant);
  1900.          end;
  1901.     end; { end case }
  1902.    Until actasmtoken = AS_SEPARATOR;
  1903.   end;
  1904.  
  1905.  
  1906.   Procedure BuildStringConstant(asciiz: boolean);
  1907.   {*********************************************************************}
  1908.   { PROCEDURE BuildStringConstant                                       }
  1909.   {  Description: Takes care of a ASCII, or ASCIIZ directive.           }
  1910.   {   asciiz: boolean -> if true then string will be null terminated.   }
  1911.   {*********************************************************************}
  1912.   { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
  1913.   { On ENTRY: Token should point to AS_STRING                           }
  1914.   {*********************************************************************}
  1915.   var
  1916.    expr: string;
  1917.    errorflag : boolean;
  1918.   Begin
  1919.       errorflag := FALSE;
  1920.       Repeat
  1921.         Case actasmtoken of
  1922.           AS_STRING: Begin
  1923.                       expr:=actasmpattern;
  1924.                       if asciiz then
  1925.                        expr:=expr+#0;
  1926.                       ConcatPasString(p,expr);
  1927.                       Consume(AS_STRING);
  1928.                     end;
  1929.           AS_COMMA:  BEGIN
  1930.                        Consume(AS_COMMA);
  1931.                      END;
  1932.           AS_SEPARATOR: ;
  1933.         else
  1934.          Begin
  1935.           Consume(actasmtoken);
  1936.           if not errorflag then
  1937.            Message(assem_e_invalid_string_expression);
  1938.           errorflag := TRUE;
  1939.          end;
  1940.     end; { end case }
  1941.    Until actasmtoken = AS_SEPARATOR;
  1942.   end;
  1943.  
  1944.  
  1945.  
  1946.  
  1947.   Procedure BuildOpCode;
  1948.   {*********************************************************************}
  1949.   { PROCEDURE BuildOpcode;                                              }
  1950.   {  Description: Parses the intel opcode and operands, and writes it   }
  1951.   {  in the TInstruction object.                                        }
  1952.   {*********************************************************************}
  1953.   { EXIT CONDITION:  On exit the routine should point to AS_SEPARATOR.  }
  1954.   { On ENTRY: Token should point to AS_OPCODE                           }
  1955.   {*********************************************************************}
  1956.   var asmtok: tasmop;
  1957.       op: tasmop;
  1958.       expr: string;
  1959.       segreg: tregister;
  1960.   Begin
  1961.     expr := '';
  1962.     asmtok := A_NONE; { assmume no prefix          }
  1963.     segreg := R_NO;   { assume no segment override }
  1964.  
  1965.     { //  opcode                          // }
  1966.     { allow for newline as in gas styled syntax }
  1967.     { under DOS you get two AS_SEPARATOR !! }
  1968.     while actasmtoken=AS_SEPARATOR do
  1969.       Consume(AS_SEPARATOR);
  1970.     if (actasmtoken <> AS_OPCODE) then
  1971.     Begin
  1972.       Message(assem_e_invalid_or_missing_opcode);
  1973.       { error recovery }
  1974.       While not (actasmtoken in [AS_SEPARATOR,AS_COMMA]) do
  1975.          Consume(actasmtoken);
  1976.       exit;
  1977.     end
  1978.     else
  1979.     Begin
  1980.       op := findopcode(actasmpattern);
  1981.       instr.addinstr(op);
  1982.       Consume(AS_OPCODE);
  1983.       { // Zero operand opcode ? // }
  1984.       if actasmtoken = AS_SEPARATOR then
  1985.         exit
  1986.       else
  1987.        operandnum := 1;
  1988.     end;
  1989.  
  1990.     While actasmtoken <> AS_SEPARATOR do
  1991.     Begin
  1992.        case actasmtoken of
  1993.          { //  Operand delimiter // }
  1994.          AS_COMMA: Begin
  1995.                   if operandnum > MaxOperands then
  1996.                     Message(assem_e_too_many_operands)
  1997.                   else
  1998.                     Inc(operandnum);
  1999.                   Consume(AS_COMMA);
  2000.                 end;
  2001.          { // End of asm operands for this opcode // }
  2002.          AS_SEPARATOR: ;
  2003.        else
  2004.          BuildOperand(instr);
  2005.      end; { end case }
  2006.     end; { end while }
  2007.   end;
  2008.  
  2009.  
  2010.  
  2011.  
  2012.   Function Assemble: Ptree;
  2013.   {*********************************************************************}
  2014.   { PROCEDURE Assemble;                                                 }
  2015.   {  Description: Parses the att assembler syntax, parsing is done      }
  2016.   {  according to GAs rules.                                            }
  2017.   {*********************************************************************}
  2018.   Var
  2019.    hl: plabel;
  2020.    labelptr,nextlabel : pasmlabel;
  2021.    commname : string;
  2022.    store_p : paasmoutput;
  2023.  
  2024.   Begin
  2025.     Message(assem_d_start_motorola);
  2026.     firsttoken := TRUE;
  2027.     operandnum := 0;
  2028.     { sets up all opcode and register tables in uppercase }
  2029.     if not _asmsorted then
  2030.     Begin
  2031.       SetupTables;
  2032.       _asmsorted := TRUE;
  2033.     end;
  2034.     p:=new(paasmoutput,init);
  2035.     { save pointer code section }
  2036.     store_p:=p;
  2037.     { setup label linked list }
  2038.     labellist.init;
  2039.     c:=asmgetchar;
  2040.     actasmtoken:=gettoken;
  2041.     while actasmtoken<>AS_END do
  2042.     Begin
  2043.       case actasmtoken of
  2044.         AS_LLABEL: Begin
  2045.                     labelptr := labellist.search(actasmpattern);
  2046.                     if not assigned(labelptr) then
  2047.                     Begin
  2048.                         getlabel(hl);
  2049.                         labellist.insert(actasmpattern,hl,TRUE);
  2050.                         ConcatLabel(p,A_LABEL,hl);
  2051.                     end
  2052.                     else
  2053.                     { the label has already been inserted into the  }
  2054.                     { label list, either as an instruction label (in}
  2055.                     { this case it has not been emitted), or as a   }
  2056.                     { duplicate local symbol (in this case it has   }
  2057.                     { already been emitted).                        }
  2058.                     Begin
  2059.                        if labelptr^.emitted then
  2060.                         Message1(assem_e_dup_local_sym,'@'+labelptr^.name^)
  2061.                        else
  2062.                         Begin
  2063.                           if assigned(labelptr^.lab) then
  2064.                             ConcatLabel(p,A_LABEL,labelptr^.lab);
  2065.                           labelptr^.emitted := TRUE;
  2066.                         end;
  2067.                     end;
  2068.                     Consume(AS_LLABEL);
  2069.                   end;
  2070.         AS_LABEL: Begin
  2071.                      { when looking for Pascal labels, these must }
  2072.                      { be in uppercase.                           }
  2073.                      if SearchLabel(upper(actasmpattern),hl) then
  2074.                        ConcatLabel(p,A_LABEL, hl)
  2075.                      else
  2076.                      Begin
  2077.                        Message1(assem_e_unknown_label_identifer,actasmpattern);
  2078.                      end;
  2079.                      Consume(AS_LABEL);
  2080.                  end;
  2081.         AS_DW:   Begin
  2082.                    Consume(AS_DW);
  2083.                    BuildConstant($ffff);
  2084.                  end;
  2085.         AS_DB:   Begin
  2086.                   Consume(AS_DB);
  2087.                   BuildConstant($ff);
  2088.                 end;
  2089.         AS_DD:   Begin
  2090.                  Consume(AS_DD);
  2091.                  BuildConstant($ffffffff);
  2092.                 end;
  2093.         AS_XDEF:
  2094.                   Begin
  2095.                    { normal units should not be able to declare }
  2096.                    { direct label names like this... anyhow     }
  2097.                    { procedural calls in asm blocks are         }
  2098.                    { supposedely replaced automatically         }
  2099.                    if (cs_compilesystem in aktswitches) then
  2100.                    begin
  2101.                      Consume(AS_XDEF);
  2102.                       if actasmtoken <> AS_ID then
  2103.                        Message(assem_e_invalid_global_def)
  2104.                       else
  2105.                         ConcatPublic(p,actasmpattern);
  2106.                       Consume(actasmtoken);
  2107.                       if actasmtoken <> AS_SEPARATOR then
  2108.                       Begin
  2109.                         Message(assem_e_line_separator_expected);
  2110.                         while actasmtoken <> AS_SEPARATOR do
  2111.                          Consume(actasmtoken);
  2112.                       end;
  2113.                    end
  2114.                    else
  2115.                    begin
  2116.                      Message(assem_w_xdef_not_supported);
  2117.                      while actasmtoken <> AS_SEPARATOR do
  2118.                        Consume(actasmtoken);
  2119.                    end;
  2120.                   end;
  2121.         AS_ALIGN: Begin
  2122.                     Message(assem_w_align_not_supported);
  2123.                     while actasmtoken <> AS_SEPARATOR do
  2124.                      Consume(actasmtoken);
  2125.                   end;
  2126.         AS_OPCODE: Begin
  2127.                    instr.init;
  2128.                    BuildOpcode;
  2129.                    instr.numops := operandnum;
  2130.                    if instr.labeled then
  2131.                      ConcatLabeledInstr(instr)
  2132.                    else
  2133.                      ConcatOpCode(instr);
  2134.                   end;
  2135.         AS_SEPARATOR:Begin
  2136.                      Consume(AS_SEPARATOR);
  2137.                      { let us go back to the first operand }
  2138.                      operandnum := 0;
  2139.                     end;
  2140.         AS_END: ; { end assembly block }
  2141.     else
  2142.       Begin
  2143.          Message(assem_e_assemble_node_syntax_error);
  2144.          { error recovery }
  2145.          Consume(actasmtoken);
  2146.       end;
  2147.     end; { end case }
  2148.   end; { end while }
  2149.   { check if there were undefined symbols.   }
  2150.   { if so, then list each of those undefined }
  2151.   { labels.                                  }
  2152.   if assigned(labellist.First) then
  2153.   Begin
  2154.     labelptr := labellist.First;
  2155.     While labelptr <> nil do
  2156.       Begin
  2157.          nextlabel:=labelptr^.next;
  2158.          if not labelptr^.emitted  then
  2159.           Message1(assem_e_local_sym_not_found_in_asm_statement,'@'+labelptr^.name^);
  2160.          labelptr:=nextlabel;
  2161.       end;
  2162.   end;
  2163.   assemble := genasmnode(p);
  2164.   labellist.done;
  2165.   Message(assem_d_finish_motorola);
  2166. end;
  2167.  
  2168. Begin
  2169.    old_exit:=exitproc;
  2170.    exitproc:=@ra68k_exit;
  2171. end.
  2172. {
  2173.   $Log: ra68k.pas,v $
  2174.   Revision 1.1.1.1.2.1  1998/07/01 13:57:09  carl
  2175.     * bugfix of -value which would be converted to +value
  2176.  
  2177.   Revision 1.1.1.1  1998/03/25 11:18:15  root
  2178.   * Restored version
  2179.  
  2180.   Revision 1.14  1998/03/22 12:45:38  florian
  2181.     * changes of Carl-Eric to m68k target commit:
  2182.       - wrong nodes because of the new string cg in intel, I had to create
  2183.         this under m68k also ... had to work it out to fix potential alignment
  2184.         problems --> this removes the crash of the m68k compiler.
  2185.       - added absolute addressing in m68k assembler (required for Amiga startup)
  2186.       - fixed alignment problems (because of byte return values, alignment
  2187.         would not be always valid) -- is this ok if i change the offset if odd in
  2188.         setfirsttemp ?? -- it seems ok...
  2189.  
  2190.   Revision 1.13  1998/03/10 16:27:43  pierre
  2191.     * better line info in stabs debug
  2192.     * symtabletype and lexlevel separated into two fields of tsymtable
  2193.     + ifdef MAKELIB for direct library output, not complete
  2194.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  2195.       working
  2196.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  2197.       working
  2198.  
  2199.   Revision 1.12  1998/03/10 01:17:25  peter
  2200.     * all files have the same header
  2201.     * messages are fully implemented, EXTDEBUG uses Comment()
  2202.     + AG... files for the Assembler generation
  2203.  
  2204. }
  2205.  
  2206.  
  2207.